﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using System.IO;

namespace WatiN.Samples.Console
{
    public class BaseUserConfigData
    {
        /// <summary>
        /// 登录电子邮件
        /// </summary>
        public string Email = string.Empty;

        /// <summary>
        /// 密码
        /// </summary>
        public string Password = string.Empty;

        /// <summary>
        /// 配置信息
        /// </summary>
        public IniConfig IniConf = null;
    }

    /// <summary>
    /// *.ini
    /// </summary>
    public class UserConfigData : BaseUserConfigData
    {
        public int MasterId = -1; // 主人家

        public bool DoParking = true; // 是否停车
        public bool DoPost = false; // 是否贴牌
        public bool DoPostLess15 = false;  //小于15分钟的是否贴条
        public bool DoReport = false; // 是否报警

        //public bool DoAutoUpgradeGarage = false; //自动买卡,买卡自动升级免费车位        
        public int DoAutoMaxCarNumber = 0; //最大车数. 当拥有的车数不到次数时会自动买车 10最大,0显然不买
        public int DoAutoUpgradeCar = 0; //自动升级车,0=不升级，1=先升级便宜的，2=先升贵的
        public int CarColor = 16711680; //默认自动升级车的颜色为红色

        public Collection<int> WhiteList = new Collection<int>(); // 停车白名单
        public Collection<int> BlackList = new Collection<int>(); // 停车黑名单
        public Collection<int> NoPostList = new Collection<int>(); // 不贴条白名单
        public Collection<int> NoReportList = new Collection<int>(); // 不报警白名单
        public Collection<int> NoParkingList = new Collection<int>(); // 不停车名单
        public Collection<int> NoBuyCarIdList = new Collection<int>(); //不买车黑名单
        public Collection<int> NoUpgradeCarIdList = new Collection<int>(); //不升级车黑名单
        public Dictionary<int, int> PostList = new Dictionary<int, int>(); // 贴条的详细设置
    }

    /// <summary>
    /// Config.txt
    /// </summary>
    public class GlobalConfigData
    {
        /// <summary>
        /// 代理服务器地址
        /// </summary>
        public string ProxyServer = string.Empty;

        /// <summary>
        /// 代理服务器端口
        /// </summary>
        public int ProxyPort = 0;

        /// <summary>
        /// 代理服务器用户名
        /// </summary>
        public string ProxyUser = string.Empty;

        /// <summary>
        /// 代理服务器密码
        /// </summary>
        public string ProxyPass = string.Empty;

        /// <summary>
        /// 链接延时时间
        /// </summary>
        public int ConnectDelayTime = 0;

        /// <summary>
        /// 如果停车失败，重新尝试的次数
        /// </summary>
        public int TryTimes = 3;

        /// <summary>
        /// 循环停车时间(分钟), 0表示只执行一次
        /// </summary>
        public int RepeatTime = 0;

        /// <summary>
        /// 设置每次链接的超时(秒)，默认是120秒
        /// </summary>
        public int HttpTimeout = 120;

        /// <summary>
        /// 设置每次HTTP请求失败后尝试的次数，默认是3次
        /// </summary>
        public int HttpTryTimes = 3;

        /// <summary>
        /// 配置信息
        /// </summary>
        public IniConfig IniConf = null;
    }

    public class ConfigHelper
    {
        public const int SLEEP_TIME = 1000;

        private ConfigHelper()
        {
        }

        public static GlobalConfigData ReadGlobalConfigData(string filename)
        {
            GlobalConfigData config = new GlobalConfigData();
            try
            {
                config.IniConf = IniHelper.ReadConfig(filename);

                IniField field;

                field = config.IniConf["system"] ?? config.IniConf[String.Empty];

                if (field != null)
                {
                    config.ProxyServer = field["ProxyServer"] ?? config.ProxyServer;
                    config.ProxyPort = ConfigHelper.GetIntegerValue(field["ProxyPort"]) ?? config.ProxyPort;
                    config.ProxyUser = field["ProxyUser"] ?? config.ProxyUser;
                    config.ProxyPass = field["ProxyPass"] ?? config.ProxyPass;
                    config.ConnectDelayTime = ConfigHelper.GetIntegerValue(field["DelayConnect"]) ?? config.ConnectDelayTime;

                    config.RepeatTime = ConfigHelper.GetIntegerValue(field["RepeatTime"]) ?? config.RepeatTime;
                    config.TryTimes = ConfigHelper.GetIntegerValue(field["TryTimes"]) ?? config.TryTimes;
                    config.HttpTimeout = (ConfigHelper.GetIntegerValue(field["HttpTimeout"]) ?? config.HttpTimeout) * 1000;
                    config.HttpTryTimes = ConfigHelper.GetIntegerValue(field["HttpTryTimes"]) ?? config.HttpTryTimes;

                    TraceLog.bWriteToFile = ConfigHelper.GetBoolValue(field["EnableLog"]) ?? false;
                }
            }
            catch (Exception e)
            {
                TraceLog.Error(e.Message);
                return null;
            }

            return config;
        }

        public static BaseUserConfigData ReadBaseUserConfigData(string filename)
        {
            BaseUserConfigData config = new BaseUserConfigData();
            try
            {
                config.IniConf = IniHelper.ReadConfig(filename);

                // 读取 [main] 段中的内容
                // 如果没有 [main] 段，则从默认段里读取配置信息（兼容以前的配置文件）
                IniField field = config.IniConf["main"] ?? config.IniConf[String.Empty];

                if (field != null)
                {
                    config.Email = field["email"];
                    config.Password = field["password"];
                }
            }
            catch (Exception e)
            {
                TraceLog.Error(e.Message);
                return null;
            }

            if (String.IsNullOrEmpty(config.Email) || String.IsNullOrEmpty(config.Password))
            {
                TraceLog.Error("文件格式不正确！");
                return null;
            }

            return config;
        }

        public static UserConfigData ReadUserConfigData(string filename)
        {
            UserConfigData config = new UserConfigData();
            try
            {
                config.IniConf = IniHelper.ReadConfig(filename);

                IniField field;
                field = config.IniConf["main"] ?? config.IniConf[String.Empty];

                if (field != null)
                {
                    config.Email = ConfigHelper.GetStringValue(field["Email"]);
                    config.Password = ConfigHelper.GetStringValue(field["Password"]);
                    config.MasterId = ConfigHelper.GetIntegerValue(field["MasterId"]) ?? config.MasterId;
                    config.DoPost = ConfigHelper.GetBoolValue(field["DoPost"]) ?? config.DoPost;
                    config.DoReport = ConfigHelper.GetBoolValue(field["DoCall"]) ?? config.DoReport;
                    config.DoParking = ConfigHelper.GetBoolValue(field["DoParking"]) ?? config.DoParking;
                    config.DoPostLess15 = ConfigHelper.GetBoolValue(field["DoPostLess15"]) ?? config.DoPostLess15;
                    ConfigHelper.GetIntegerListValue(config.WhiteList, field["WhiteList"]);
                    ConfigHelper.GetIntegerListValue(config.BlackList, field["BlackList"]);
                    ConfigHelper.GetIntegerListValue(config.NoPostList, field["NoPostList"]);
                    ConfigHelper.GetIntegerListValue(config.NoReportList, field["NoCallList"]);
                    ConfigHelper.GetIntegerListValue(config.NoParkingList, field["NoParkingList"]);
                    ConfigHelper.GetIntegerListValue(config.NoBuyCarIdList, field["NoBuyCarIdList"]);
                    ConfigHelper.GetIntegerListValue(config.NoUpgradeCarIdList, field["NoUpgradeCarIdList"]);
                    config.DoAutoMaxCarNumber = ConfigHelper.GetIntegerValue(field["DoAutoMaxCarNumber"]) ?? config.DoAutoMaxCarNumber;
                    config.CarColor = ConfigHelper.GetIntegerValue(field["CarColor"]) ?? config.CarColor;
                    config.DoAutoUpgradeCar = ConfigHelper.GetIntegerValue(field["DoAutoUpgradeCar"]) ?? config.DoAutoUpgradeCar;

                    string postInfoStr = field["Post"] ?? String.Empty;
                    string[] postInfos = postInfoStr.Split('|');
                    foreach (string postInfo in postInfos)
                    {
                        Match match = Regex.Match(postInfo, @" *([0-9]+|\*) *, *([0-9]+|\*) *");
                        if (match.Success)
                        {
                            string struid = match.Result("$1");
                            string strprofit = match.Result("$2");

                            int uid;
                            int profit;

                            if (!Int32.TryParse(struid, out uid))
                            {
                                uid = -1;
                            }
                            if (!Int32.TryParse(strprofit, out profit))
                            {
                                profit = -1;
                            }
                            config.PostList[uid] = profit;
                        }
                    }
                }

            }
            catch (Exception e)
            {
                TraceLog.Error(e.Message);
                return null;
            }

            if (String.IsNullOrEmpty(config.Email) || String.IsNullOrEmpty(config.Password))
            {
                TraceLog.Error("文件格式不正确！");
                return null;
            }

            if (config.MasterId > 0)
            {
                config.NoPostList.Remove(config.MasterId);
                config.NoPostList.Add(config.MasterId);
            }
            return config;
        }

        public static void GetIntegerListValue(Collection<int> list, string line)
        {
            string[] idlist = GetStringValue(line).Split(',');
            foreach (string id in idlist)
            {
                int value = ConfigHelper.GetInteger(id);
                if (-1 != value)
                {
                    list.Add(value);
                }
            }
        }

        public static int GetInteger(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return -1;
            }
            int id;
            if (int.TryParse(str, out id))
            {
                return id;
            }
            return -1;
        }

        //public static bool GetBoolValue(string line)
        //{
        //    return ("1" == GetStringValue(line));
        //}

        //public static int GetIntegerValue(string line)
        //{
        //    string value = GetStringValue(line);

        //    return ConfigHelper.GetInteger(value);
        //}

        public static string GetStringValue(string line)
        {
            return line.Substring(line.IndexOf('=') + 1);
        }

        ///// <summary>
        ///// baseObject -> subObject
        ///// 从基类实例复制所有公共实例的字段的值到派生类实例，并返回派生类实例
        ///// </summary>
        ///// <typeparam name="T">要返回的派生类类型</typeparam>
        ///// <param name="baseObject">基类实例</param>
        ///// <returns>派生类实例</returns>
        //public static T BaseObj2SubObj<T>(object baseObject)
        //{
        //    if (baseObject == null)
        //        return default(T);

        //    Type baseClass = baseObject.GetType();//基类类型
        //    Type subClass = typeof(T);

        //    System.Reflection.FieldInfo[] baseFields = baseClass.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);//基类所有的公共实例字段

        //    T subObject;
        //    try
        //    {
        //        subObject = (T)Activator.CreateInstance(subClass);// 创建一个派生类实例

        //        for (int i = 0; i < baseFields.Length; i++)
        //        {
        //            //从派生类获取和基类具有同一名字的公共实例字段
        //            System.Reflection.FieldInfo current = subClass.GetField(baseFields[i].Name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
        //            if (current != null)
        //            {
        //                //复制字段
        //                current.SetValue(subObject, baseFields[i].GetValue(baseObject));
        //            }
        //        }
        //    }
        //    catch { return default(T); }
        //    return subObject;
        //}

        public static Nullable<bool> GetBoolValue(string strvalue)
        {
            if (String.IsNullOrEmpty(strvalue))
            {
                return null;
            }
            else
            {
                return ("1" == strvalue);
            }
        }

        public static Nullable<int> GetIntegerValue(string strvalue)
        {
            if (String.IsNullOrEmpty(strvalue))
            {
                return null;
            }

            int ret;

            if (!Int32.TryParse(strvalue, out ret))
            {
                ret = -1;
            }

            return ret;
        }
    }
}
